package service

import (
	"context"
	"github.com/shopspring/decimal"
	"insighttracking/common/enum"
	"insighttracking/common/utils"
	"insighttracking/query/dao"
	"insighttracking/query/model"
	"time"
)

type _productionSortingService struct{}

func (s _productionSortingService) CreateApi(ctx context.Context, tx *dao.QueryTx, enterPriseID int64, operatorID int64, operator string, weight decimal.Decimal, productionPlanDetailID int64, spuID int64) (productionBatchNumber string, err error) {
	productionBatchNumber = utils.UuIdV4()[:16] + time.Now().Format("20060102")
	entity := model.ProductionSortingEntity{
		ProductionBatchNumber:  productionBatchNumber,
		EnterpriseID:           enterPriseID,
		ProductionPlanDetailID: productionPlanDetailID,
		SpuID:                  spuID,
		Weight:                 weight,
		ActualWeight:           weight,
		Status:                 0,
		Type:                   1,
		Deviation:              decimal.Zero,
		OperatorID:             operatorID,
		Operator:               operator,
		ReceiveTime:            time.Date(1970, time.January, 1, 0, 0, 0, 0, time.UTC),
	}
	err = tx.ProductionSortingEntity.WithContext(ctx).Create(&entity)
	return
}

func (s _productionSortingService) GetByBatchNumber(ctx context.Context, productionBatchNumber string) (*model.ProductionSortingEntity, error) {
	return dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.ProductionBatchNumber.Eq(productionBatchNumber)).First()
}

func (s _productionSortingService) GetByPlanDetailID(ctx context.Context, productionPlanDetailID int64) ([]*model.ProductionSortingEntity, error) {
	return dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.ProductionPlanDetailID.Eq(productionPlanDetailID)).Order(dao.ProductionSortingEntity.CreatedAt.Desc()).Find()
}

func (s _productionSortingService) ResetOne(ctx context.Context, tx *dao.QueryTx, productionBatchNumber string) (err error) {
	_, err = tx.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.ProductionBatchNumber.Eq(productionBatchNumber)).Delete()
	return err
}

func (s _productionSortingService) ResetAll(ctx context.Context, tx *dao.QueryTx, productionPlanDetailID int64) (err error) {
	_, err = tx.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.ProductionPlanDetailID.Eq(productionPlanDetailID)).Delete()
	return err
}

func (s _productionSortingService) BindOne(ctx context.Context, productionBatchNumber string, orderSpuID int64) (err error) {
	_, err = dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.ProductionBatchNumber.Eq(productionBatchNumber)).UpdateSimple(
		dao.ProductionSortingEntity.OrdersSpuID.Value(orderSpuID),
		dao.ProductionSortingEntity.Status.Value(enum.ProductionSortingPrepare))
	return
}

func (s _productionSortingService) UnBindOne(ctx context.Context, productionBatchNumber string) (err error) {
	_, err = dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.ProductionBatchNumber.Eq(productionBatchNumber)).UpdateSimple(
		dao.ProductionSortingEntity.OrdersSpuID.Value(0),
		dao.ProductionSortingEntity.Status.Value(enum.ProductionSortingInit))
	return
}

func (s _productionSortingService) GetBySpuID(ctx context.Context, spuID int64) ([]*model.ProductionSortingEntity, error) {
	return dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.SpuID.Eq(spuID)).Order(dao.ProductionSortingEntity.CreatedAt.Desc()).Find()
}

func (s _productionSortingService) GetSortedWeight(ctx context.Context, productionPlanDetailID int64) (weight decimal.Decimal, err error) {
	err = dao.ProductionSortingEntity.WithContext(ctx).Select(dao.ProductionSortingEntity.Weight.Sum()).Where(dao.ProductionSortingEntity.ProductionPlanDetailID.Eq(productionPlanDetailID)).Group(dao.ProductionSortingEntity.ProductionPlanDetailID).Pluck(dao.ProductionSortingEntity.Weight, &weight)
	return
}

func (s _productionSortingService) GetSortedPackage(ctx context.Context, productionPlanDetailID int64) (count int64, err error) {
	return dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.ProductionPlanDetailID.Eq(productionPlanDetailID)).Count()
}

func (s _productionSortingService) GetSpuSortedWeight(ctx context.Context, ordersSpuIDs []int64) (weight decimal.Decimal, err error) {
	err = dao.ProductionSortingEntity.WithContext(ctx).Select(dao.ProductionSortingEntity.Weight.Sum()).Where(
		dao.ProductionSortingEntity.OrdersSpuID.In(ordersSpuIDs...)).Group(dao.ProductionSortingEntity.EnterpriseID).Pluck(dao.ProductionSortingEntity.Weight, &weight)
	return
}

func (s _productionSortingService) GetPackedCount(ctx context.Context, ordersSpuID int64) (count int64, err error) {
	return dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.OrdersSpuID.Eq(ordersSpuID)).Count()
}

func (s _productionSortingService) GetPackedWeight(ctx context.Context, ordersSpuID int64) (weight float64, err error) {
	err = dao.ProductionSortingEntity.WithContext(ctx).Select(dao.ProductionSortingEntity.Weight.Sum()).Where(dao.ProductionSortingEntity.OrdersSpuID.Eq(ordersSpuID)).Group(dao.ProductionSortingEntity.OrdersSpuID).Pluck(dao.ProductionSortingEntity.Weight, &weight)
	return
}

func (s _productionSortingService) GetReceivedCount(ctx context.Context, ordersSpuID int64) (count int64, err error) {
	return dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.OrdersSpuID.Eq(ordersSpuID), dao.ProductionSortingEntity.Status.Eq(enum.ProductionSortingReceived)).Count()
}

func (s _productionSortingService) GetPackedList(ctx context.Context, ordersSpuID int64) ([]*model.ProductionSortingEntity, error) {
	return dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.OrdersSpuID.Eq(ordersSpuID)).Order(dao.ProductionSortingEntity.CreatedAt.Desc()).Find()
}

func (s _productionSortingService) GetUnshippedPackedList(ctx context.Context, enterpriseID, spuID int64) ([]*model.ProductionSortingEntity, error) {
	tx := dao.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.EnterpriseID.Eq(enterpriseID), dao.ProductionSortingEntity.Status.Lt(enum.ProductionSortingOutSend))
	if spuID > 0 {
		tx = tx.Where(dao.ProductionSortingEntity.SpuID.Eq(spuID))
	}
	return tx.Order(dao.ProductionSortingEntity.CreatedAt.Desc()).Find()
}

func (s _productionSortingService) OutSendByOrdersSpuIDApi(ctx context.Context, tx *dao.QueryTx, ordersSpuID int64) error {
	_, err := tx.ProductionSortingEntity.WithContext(ctx).Where(dao.ProductionSortingEntity.OrdersSpuID.Eq(ordersSpuID)).UpdateSimple(dao.ProductionSortingEntity.Status.Value(enum.ProductionSortingOutSend))
	return err
}

var ProductionSortingService = new(_productionSortingService)
